import json
import time

from utils.AssertUtil import AssertUtil
from utils.YamlUtil import YamlUtil
from utils.log_util import logger


class ExtractUtil:
    def __init__(self):
        self.jsonpath_util = AssertUtil()   # 将类AssertUtil实例化并直接化为类ExtractUtil的一个变量
        self.yaml_util = YamlUtil()
    def extract_data(self, res, extract):
        """
        根据extract表达式，获取接口内容并存入yaml
        :param res: res.json()
        :param extract: eg $.token
        :return:
        """
        if extract:
            for key, expression in extract.items():
                try:
                    value = self.jsonpath_util.extract_by_jsonpath(res,expression)
                    #写入value
                    self.yaml_util.write_extra_yaml({key: value})
                except Exception as e:
                    logger.error(f'变量{key}写入extract.yaml失败，请检查，error={e}')

    def get_extract_value(self,key):
        """从extract.yaml中获取内容"""
        try:
            data = self.yaml_util.read_extract_yaml()
            return data[key]
        except Exception as e:
            logger.error(f"从yaml中根据{key}获取不到内容，error={e}")

    def extract_url(self, url):
        # /orders/${get_extract_value(order_id)}/
        if "${" in url and "}" in url:
            return self.process_data(url)
        return url

    # process过程，加工，这个函数用来处理yaml数据，将数据里的变量名提取出来
    def process_data(self, data):
        """处理字符串，把函数弄出来"""
        for i in range(data.count("${")):
            if "${" in data and "}" in data:
                start_index = data.index('$')
                end_index = data.index('}')
                # 获取函数中的方法
                func_full_name = data[start_index: end_index + 1]
                # 获取函数名
                func_name = data[start_index + 2: data.index('(')]
                # 获取函数中的参数
                func_params = data[data.index('(')+1: data.index(')')]
                extract_data = getattr(self, func_name)(*func_params.split(',') if func_params else '') #1、适用于多个参数，(*func_params.split(','))此处因为func_params这个变量的值是个str，所以先以‘，’分隔出多个参数,再通过*表达式解分隔出来的参数组,但需要注意一点，因为是用字符串分隔出来的所以解出来的还是字符串，相加的话就会成为字符串拼接。2、(*func_params.split(',') if func_params else '')用了三元表达式：结果 = 选项一 if 条件 else 选项二，此处并没有严格遵照结果=的形式写，可见去掉结果=这部分直接将三元表达式放在在表达式中也是可行的？
                #extract_data = getattr(self,func_name)(func_params)   #适用于一个参数，即：getattr(ExtractUtil(),'get_extract_value')(func_params):类反射：getattr(实例化类,'类的函数名')(函数的参数)，这里因为就写在类的里面所以实例化类可直接用self代替，getattr除了能通过‘函数名’获取成员方法/启动成员方法，还可以通过‘类变量’获取类变量，以及通过‘成员变量’获得成员变量
                """
                getattr大概指南：具体查看https://zhuanlan.zhihu.com/p/576254496
                class Person():
                    # 定义类变量
                    guoJi = "china"
                
                    def __init__(self,name,age,id):
                        self.name = name
                        self.age = age
                        self.id = id
                
                    def my_info(self):
                        my_name = self.name
                        print(my_name)
                # 创建类的对象
    xiao_wang = Person("小王",23,"101010")
    
    print(Person.guoJi)
    # 反射获取类变量
    print(getattr(Person, 'guoJi'))
    
    # 反射获取成员变量
    print(getattr(xiao_wang,"name"))
    
    # 反射获取成员方法，返回方法是一个引用地址，要想执行该方法，需要在后面加上小括号
    getattr(xiao_wang,"my_info")()
    
    # 如果在对象或者类中找不倒指定的字符串，则报AttributeError出错误
    # print(getattr(xiao_wang,"name11"))
    # getattr(xiao_wang,"my_info11")()
                """
                data = data.replace(func_full_name,str(extract_data)) #str.replace('需要被替换的部分str','替换的str'), 如 ‘abc’.replace('b','c')——>'acc'
        return data

    def test_add(self,a,b):
        return a+b

    def extract_case(self, case_info):
        #转换成json str类型
        str_case_info = json.dumps(case_info)
        data = self.process_data(str_case_info)
        # 转换成json类型
        return  json.loads(data)

    def get_time(self):
        timestamp = int(time.time())
        return timestamp
